/*
 * This file is part of ELCube.
 *
 * ELCube is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * ELCube is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with ELCube.  If not, see <https://www.gnu.org/licenses/>.
 */
package cn.nkpro.elcube;

import cn.nkpro.elcube.cloud.NkAbstractDubboConsumerAutoRegistrar;
import cn.nkpro.elcube.cloud.NkCloudMQManager;
import cn.nkpro.elcube.cloud.NkCloudProperties;
import cn.nkpro.elcube.docengine.NkDocProperties;
import cn.nkpro.elcube.docengine.NkDocSearchService;
import cn.nkpro.elcube.docengine.cloud.NkCloudDocEngine;
import cn.nkpro.elcube.docengine.cloud.NkCloudDocEngineLock;
import cn.nkpro.elcube.docengine.cloud.NkCloudDocEngineLockImpl;
import cn.nkpro.elcube.docengine.cloud.NkCloudDocSearchService;
import cn.nkpro.elcube.docengine.gen.DocDefH;
import cn.nkpro.elcube.docengine.service.NkDocDefService;
import cn.nkpro.elcube.docengine.service.NkDocEngineFrontService;
import cn.nkpro.elcube.docengine.service.SequenceSupport;
import cn.nkpro.elcube.docengine.service.impl.NkDocEngineServiceImpl;
import cn.nkpro.elcube.docengine.service.impl.NkDocSearchServiceImpl;
import cn.nkpro.elcube.docengine.service.sequences.DefaultSequenceSupportImpl;
import cn.nkpro.elcube.task.DefaultBpmTaskServiceImpl;
import cn.nkpro.elcube.task.NkBpmTaskService;
import cn.nkpro.elcube.task.impl.NkBpmTaskServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.*;
import org.springframework.core.env.Environment;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.Collections;
import java.util.List;


@EnableAspectJAutoProxy
@EnableConfigurationProperties(NkDocProperties.class)
@Configuration
public class NkDocEngineAutoConfiguration implements ApplicationRunner, WebMvcConfigurer {


    @Value("${nk.cloud.id:}")
    private String cloudId;

    @Autowired
    private NkDocDefService docDefService;

    @Autowired(required = false)
    private NkCloudMQManager cloudMQManager;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        NkDocSearchService().init();

        if(StringUtils.isNotBlank(cloudId)){
            for(DocDefH docDefH : docDefService.getAllActiveDocTypes()){
                if(StringUtils.isNotBlank(docDefH.getCloudSyncSubscribeId())){
                    cloudMQManager.declareBinding("$"+docDefH.getDocType()+"@"+docDefH.getCloudSyncSubscribeId());
                }
            }
        }
    }
    /**
     * 单据编号序列配置
     */
    @ConditionalOnMissingBean
    @Bean
    public SequenceSupport sequenceSupport(){
        return new DefaultSequenceSupportImpl();
    }

    /**
     * 开始配置云服务
     */
    @ConditionalOnProperty(value = "nk.cloud.id")
    @Configuration
    @Import({
            DubboConsumerAutoRegistrar.class,
            DubboEngineLockAutoRegistrar.class
    })
    public static class NkDocEngineCloudConfig {}
    static class DubboConsumerAutoRegistrar extends NkAbstractDubboConsumerAutoRegistrar {
        @Override
        protected Class<?>[] registrarClass() {
            return new Class[]{
                    NkDocEngineFrontService.class,
                    NkDocSearchService.class,
                    NkBpmTaskService.class
            };
        }
    }

    /**
     * slave模式，启用远程的单据引擎锁
     */
    static class DubboEngineLockAutoRegistrar extends NkAbstractDubboConsumerAutoRegistrar {
        @Override
        protected Class<?>[] registrarClass() {
            return new Class[]{
                    NkCloudDocEngineLock.class
            };
        }
        @Override
        protected List<String> cloudIds(Environment env) {
            NkCloudProperties.Mode mode = env.getProperty("nk.cloud.mode", NkCloudProperties.Mode.class);
            if(mode== NkCloudProperties.Mode.CLOUD){
                String masterId = env.getProperty("nk.cloud.mdm-id");
                if(StringUtils.isNotBlank(masterId)){
                    return Collections.singletonList(masterId);
                }
            }
            return Collections.emptyList();
        }
    }

    /**
     * MDM模式，启用本地的单据引擎锁
     */
    @ConditionalOnProperty(value = "nk.cloud.mode",havingValue = "MDM")
    @Bean
    @DubboService
    public NkCloudDocEngineLock NkDocEngineLock(){
        return new NkCloudDocEngineLockImpl();
    }

    @Bean
    @DubboService
    public NkDocEngineFrontService NkDocEngineFrontService(){
        return new NkDocEngineServiceImpl();
    }
    /**
     * 启用代理
     */
    @ConditionalOnProperty(value = "nk.cloud.id")
    @Primary
    @Bean
    public NkCloudDocEngine NkCloudDocEngine(){
        return new NkCloudDocEngine();
    }

    @Bean
    @DubboService
    public NkDocSearchService NkDocSearchService(){
        return new NkDocSearchServiceImpl();
    }
    /**
     * 启用代理
     */
    @ConditionalOnProperty(value = "nk.cloud.id")
    @Primary
    @Bean
    public NkDocSearchService NkCloudDocSearchService(){
        return new NkCloudDocSearchService();
    }

    @Primary
    @Bean
    @DubboService
    public NkBpmTaskService NkBpmTaskService(){
        return new NkBpmTaskServiceImpl();
    }

    /**
     * 暂时没有用
     */
    @ConditionalOnMissingBean
    @Bean("NkBpmTaskService")
    public NkBpmTaskService nkBpmTaskService(){
        return new DefaultBpmTaskServiceImpl();
    }
}
